# -*- coding:utf-8 -*-
# @Author : mistchan
# @Time : 2023/3/19 0019 19:38
# @File : main.py
# @Software: PyCharm
import sys
import json, os
import traceback

from PyQt5.QtCore import Qt, QRegExp
from PyQt5.QtGui import QCursor, QShowEvent, QRegExpValidator
from PyQt5.QtWidgets import QApplication, QWidget, QDesktopWidget, QHBoxLayout, QVBoxLayout, QHeaderView
from PyQt5.QtWidgets import QPushButton, QLineEdit, QTableView,QLabel, QCheckBox
from PyQt5.QtWidgets import QMessageBox, QMenu, QAbstractItemView
from PyQt5.QtSql import QSqlDatabase, QSqlQuery, QSqlTableModel
from dip_tool import DipThread
class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        # 全局控件
       
        self.txt_asin = None
        self.table_view = None
        # 窗体标题
        self.setWindowTitle("DIP2023 by cbl v1.0")
        # 尺寸
        self.resize(1000, 800)
        # 位置
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)

        # 创建布局
        layout = QVBoxLayout()

        layout.addLayout(self.init_header())
        layout_content = QHBoxLayout()
        
        layout_diagnoses = QVBoxLayout()
        layout_diagnoses.addLayout(self.init_form())

        layout_diagnoses.addLayout(self.init_table())

        layout_content.addLayout(layout_diagnoses)
        layout_content.addLayout(self.init_info())
        layout_content.setStretch(0, 1)
        layout_content.setStretch(1, 1)
        layout.addLayout(layout_content)
        layout.addLayout(self.init_footer())

        # 给窗体设置元素的排列方式
        self.setLayout(layout)
        
        # self.old_hook = sys.excepthook
        # sys.excepthook = self.error_win
    def showEvent(self, a0: QShowEvent) -> None:
        # 控件都渲染出来后再处理焦点问题
        self.txt_asin.setFocus()
        self.model.setSort(4, Qt.DescendingOrder)  #排序
        self.model.select()
        return super().showEvent(a0)
    def closeEvent(self, event):
        # 退出确认
        reply = QMessageBox.question(self,u"警告", u"确认退出？", QMessageBox.Yes, QMessageBox.No)
        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()
    def init_header(self):
        # 1.创建顶部菜单布局
        header_layout = QHBoxLayout()
        # 1.1创建两个按钮
        # btn_start = QPushButton('全部更新')s
        
        # btn_start.clicked.connect(self.event_refresh_all)
        # header_layout.addWidget(btn_start)
        
        return header_layout

    def init_form(self):
        # 2.创建上边标题布局
        form_layout = QVBoxLayout()
        # 2.0 花费
        cost_layout = QHBoxLayout()
        cost_label = QLabel("花费：")
        cost_layout.addWidget(cost_label)
        txt_asin_cost = QLineEdit()
        txt_asin_cost.setPlaceholderText("请输入花费钱数")
        reg = QRegExp('[0-9]+$')
        validator = QRegExpValidator()
        validator.setRegExp(reg)
        txt_asin_cost.setValidator(validator)
        txt_asin_cost.setClearButtonEnabled(True)
        self.txt_asin_cost = txt_asin_cost
        cost_layout.addWidget(txt_asin_cost)
        form_layout.addLayout(cost_layout)
        # 2.1输入框
        txt_ly = QHBoxLayout()
        txt_asin = QLineEdit()
        txt_asin.setPlaceholderText("请输入诊断名称或编码或简拼查询")
        
        self.chekbx = chekbx =QCheckBox('模糊查询')
        chekbx.setChecked(True)
        chekbx.stateChanged.connect(self.search_content)
        txt_ly.addWidget(txt_asin)
        self.txt_asin = txt_asin
        txt_asin.textChanged.connect(self.search_content)

        txt_ly.addWidget(chekbx)
        form_layout.addLayout(txt_ly)
        return form_layout

    def init_table(self):

        # 3.创建中间表格布局
        self.table_layout = QHBoxLayout()
        # 3.1创建表格
        self.table_view = QTableView()
        if not os.path.exists('.\\dip\\data_dip.db'):
            self.init_sql()
        con = QSqlDatabase.addDatabase('QSQLITE')

        con.setDatabaseName('.\\dip\\data_dip.db')
        if not con.open():
            print(con.lastError().text())
            return
        self.model = QSqlTableModel(self)
        self.model.setTable('dip_2023')
        self.model.setHeaderData(1, Qt.Horizontal, "编码")
        self.model.setHeaderData(2, Qt.Horizontal, "诊断")
        self.model.setHeaderData(4, Qt.Horizontal, "查询次数")
        # self.model.setFilter("use_counts>0")
        self.model.setFilter("use_counts>0")
        # query = QSqlQuery("select code, name from dip_2023 order by use_counts desc limit 1")
        # self.model.setQuery(query)
        # self.model.query()
        self.model.select()
        
        font = self.table_view.horizontalHeader().font()  # 获取当前表头的字体
        font.setFamily("微软雅黑")  # 修改字体设置
        self.table_view.horizontalHeader().setFont(font)  # 重新设置表头的字体
        
        self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
        self.table_view.clicked.connect(self.show_info)
        # 禁止编辑
        self.table_view.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table_view.setContextMenuPolicy(Qt.CustomContextMenu)  # 设置策略为自定义菜单
        self.table_view.customContextMenuRequested.connect(self.ContextMenu)  # 菜单内容回应信号槽
        self.table_view.setModel(self.model)
        self.table_view.setSortingEnabled(True)
        for i in range(self.model.columnCount()):
            if i in [0,3, ]:
                self.table_view.setColumnHidden(i, True)
        self.table_layout.addWidget(self.table_view)
        return self.table_layout
    def init_info(self):
        # 3.创建中间布局
        self.info_layout = QVBoxLayout()
        # 3.1创建标签
        self.title_label = title_label = QLabel()
        title_label.setText("DIP分组预览")
        title_label.setAlignment(Qt.AlignCenter)
        self.info_label = info_label = QLabel()
        self.info_layout.addWidget(title_label)
        self.info_layout.addWidget(info_label)
        self.info_layout.addStretch()
        
        return self.info_layout
    def init_footer(self):
        # 4.创建底部菜单布局
        footer_layout = QHBoxLayout()
        # 4.1状态条
        self.label_status = label_status = QLabel('')
        footer_layout.addWidget(label_status)
        # 占位弹簧
        footer_layout.addStretch()
        # 4.2按钮


        btn_bc = QPushButton('初始化数据库')
        btn_bc.clicked.connect(self.init_sql)
        footer_layout.addWidget(btn_bc)
        return footer_layout

   # 查询

    def search_content(self):

        keywords = self.txt_asin.text().strip()
        if keywords:
            flag = self.chekbx.checkState()
            if not flag:
                self.model.setFilter("name like '{}%' or code like '{}%' or spell like '{}%'".format(keywords, keywords, keywords))
            else:
                self.model.setFilter("code||name||spell like '%{}%'".format(keywords))
            self.model.select()
            self.table_view.setModel(self.model)
        else:
            self.model.select()
            self.table_view.setModel(self.model)

    def show_info(self, item=None):
        if item is None:
            return
        else:

            row = item.row()
            # col = item.column()
            try:
                cost = self.txt_asin_cost.text()
                if not cost:
                    QMessageBox.critical(self, "错误！", "请输入花费的钱数！")
            
                    return
                code = self.table_view.model().index(row, 1).data()
                name = self.table_view.model().index(row, 2).data()
                use_c = self.table_view.model().index(row, 4).data()
                
                self.model.setData(self.model.index(row, 4), use_c+1)
                self.model.submitAll()
                
                thread = DipThread(code, name, cost, self)
                thread.success.connect(self.dip_success_callback)
                thread.error.connect(self.dip_error_callback)

                thread.start()
                
            except Exception as e:
                return
    def dip_success_callback(self, result, url):
        status = result.get("code")
        if int(status) != 200:
            QMessageBox.critical(self, "错误！", f"网络错误：{status}")
            return
        
        print(result)
        data = result.get("data")
        group = data.get("group")
        info = f"总费用：{self.txt_asin_cost.text()} DIP费用：{group.get('dipAvgCostStd')} 差额：{group.get('estimateClearDiff')}\nDIP诊断：【{group.get('dipNameSub')}】分值：【{group.get('score')}】\n类别：【{group.get('warnLevel')}】{group.get('warnCaption')}\n其他建议：\n"
        recommends = data.get("repeatResults")
        n = 1
        for each in recommends:
            reco = f"{n}.诊断：{each['dipName']}({each['dipCode']}) 手术：{each.get('surgeryMainName')}({each['surgeryMainCode']}) 费用：{each['hospitalTotalAvg']}\n"
            n+=1
            info += reco
        self.info_label.setText(info)
        self.title_label.setText(f"<a href='{url}'>点击打开【DIP分组预览】</a>")
        self.title_label.setOpenExternalLinks(True)


        
    def dip_error_callback(self, error):
        QMessageBox.critical(self, "错误！", f"{error}")
        

    def ContextMenu(self, pos):
        # 表格上的右键菜单
        row = self.table_view.currentIndex().row()  # 获取被选择的行数
        model = self.table_view.model()  # 获取被选择的模型
        pos = self.table_view.mapFromGlobal(QCursor.pos())  # 获取表格中鼠标坐标
        it = self.table_view.columnAt(pos.x())  # 根据鼠标坐标获取列号
        Comp = model.index(row, it).data()  # 根据模型获取第row行第it列(从0开始算第1列)的内容
        menu = QMenu()

        item_fresh = menu.addAction("更新")
        item_copy = menu.addAction("复制")

        action = menu.exec_(self.table_view.mapToGlobal(pos))
        if action == item_copy:  # 复制功能

            clipboard = QApplication.clipboard()
            text_copied = Comp
            clipboard.setText(text_copied)
           

        if action == item_fresh:
            pass

    def init_sql(self):
        # 初始化数据库
    
        db = QSqlDatabase.addDatabase('QSQLITE')  # 指定数据库类型
        # 指定SQLite数据库文件名
        db.setDatabaseName('.\\dip\\data_dip.db')  # muttonDB.db之前的目录都要存在才可建立成功！数据库名字自己随便起
        if not db.open():
            QMessageBox.critical(self, "错误！", "无法建立与数据库的连接！")
            return
        query = QSqlQuery()
        query.exec('SELECT name FROM sqlite_master WHERE name="dip_2023"')
        if query.first():
        
            QMessageBox.information(self, "操作已取消", "数据表已存在，无需初始化。")
        else:
            with open('.\\dip\\key_words_sql.json', 'r', encoding='utf8') as fk:
                key_words_sql = json.load(fk)
            with open('.\\dip\\key_words.json', 'r', encoding='utf8') as fkw:
                key_words = json.load(fkw)
            sql_ = ", ".join(key_words_sql)
            columns = ', '.join(key_words)
            placeholders = ', '.join('?' * len(key_words))
            # 诊断
            sql_dias = f'create table dip_2023 (`id` INTEGER PRIMARY KEY, {sql_})'

            query.exec(sql_dias)
            with open('.\\dip\\dip_diagnoses.json', 'r', encoding='utf8') as f:
                dip_diagnoses = json.load(f)
            
            sql = 'INSERT INTO dip_2023({}) VALUES ({})'.format(columns, placeholders)
            query.prepare(sql)
            
            for data in dip_diagnoses['data']:
                print(data)
                for each in key_words:
                    query.addBindValue(str(data.get(each)))

                query.exec()
            # for each in key_words:
                
            #     query.addBindValue((str(data.get(each)) for data in dip_diagnoses['data']))
            # query.execBatch()   
            # 手术
            sql_operations = f'create table dip_operations (`id` INTEGER PRIMARY KEY, {sql_})'

            query.exec(sql_operations)
            with open('.\\dip\\dip_operations.json', 'r', encoding='utf8') as f:
                dip_operations = json.load(f)
            
            
            sql_op = 'INSERT INTO dip_operations ({}) VALUES ({})'.format(columns, placeholders)
            
            query.prepare(sql_op)
            for data in dip_operations['data']:
                for each in key_words:

                    query.addBindValue(str(data.get(each)))

                query.exec()
            # for each in key_words:
            #     query.addBindValue((str(data.get(each)) for data in dip_operations['data']))
            # query.execBatch() 
            
            QMessageBox.information(self, "成功", "数据库已完成初始化。")

        db.close()


    def error_win(self, ty,vals, tracebk):
        # 全局捕获异常，弹窗提示，避免程序因异常关闭
        tracebk_format = traceback.format_exception(ty, vals, tracebk)
        
        tracbk_string = f"{tracebk_format[-1]}"
        QMessageBox.critical(self, "运行出错!", f"程序运行时出现了一个致命错误!\n请联系管理员解决。\n详细错误信息：\n{tracbk_string}")
        # print(f"程序运行时出现了一个致命错误!\n请联系管理员解决。\n详细错误信息：\n{tracbk_string}")
        self.old_hook(ty, vals, tracebk)
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())
